home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2000 Spring / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).7z / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).bin / DXF / samples / multimedia / dsound / src / voicemanagement / wavread.cpp < prev    next >
C/C++ Source or Header  |  1999-07-26  |  10KB  |  300 lines

  1. //-----------------------------------------------------------------------------
  2. // File: WavRead.cpp
  3. //
  4. // Desc: Wave file support for loading and playing Wave files using DirectSound 
  5. //       buffers.
  6. //
  7. // Copyright (c) 1999 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #include <windows.h>
  10. #include "WavRead.h"
  11.  
  12.  
  13.  
  14.  
  15. //-----------------------------------------------------------------------------
  16. // Defines, constants, and global variables
  17. //-----------------------------------------------------------------------------
  18. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  19. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  20.  
  21.  
  22.  
  23.  
  24. //-----------------------------------------------------------------------------
  25. // Name: ReadMMIO()
  26. // Desc: Support function for reading from a multimedia I/O stream
  27. //-----------------------------------------------------------------------------
  28. HRESULT ReadMMIO( HMMIO hmmioIn, MMCKINFO* pckInRIFF, WAVEFORMATEX** ppwfxInfo )
  29. {
  30.     MMCKINFO        ckIn;           // chunk info. for general use.
  31.     PCMWAVEFORMAT   pcmWaveFormat;  // Temp PCM structure to load in.       
  32.  
  33.     *ppwfxInfo = NULL;
  34.  
  35.     if( ( 0 != mmioDescend( hmmioIn, pckInRIFF, NULL, 0 ) ) )
  36.         return E_FAIL;
  37.  
  38.     if( (pckInRIFF->ckid != FOURCC_RIFF) ||
  39.         (pckInRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E') ) )
  40.         return E_FAIL;
  41.  
  42.     // Search the input file for for the 'fmt ' chunk.
  43.     ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
  44.     if( 0 != mmioDescend(hmmioIn, &ckIn, pckInRIFF, MMIO_FINDCHUNK) )
  45.         return E_FAIL;
  46.  
  47.     // Expect the 'fmt' chunk to be at least as large as <PCMWAVEFORMAT>;
  48.     // if there are extra parameters at the end, we'll ignore them
  49.        if( ckIn.cksize < (LONG) sizeof(PCMWAVEFORMAT) )
  50.            return E_FAIL;
  51.  
  52.     // Read the 'fmt ' chunk into <pcmWaveFormat>.
  53.     if( mmioRead( hmmioIn, (HPSTR) &pcmWaveFormat, 
  54.                   sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat) )
  55.         return E_FAIL;
  56.  
  57.     // Allocate the waveformatex, but if its not pcm format, read the next
  58.     // word, and thats how many extra bytes to allocate.
  59.     if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM )
  60.     {
  61.         if( NULL == ( *ppwfxInfo = new WAVEFORMATEX ) )
  62.             return E_FAIL;
  63.  
  64.         // Copy the bytes from the pcm structure to the waveformatex structure
  65.         memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  66.         (*ppwfxInfo)->cbSize = 0;
  67.     }
  68.     else
  69.     {
  70.         // Read in length of extra bytes.
  71.         WORD cbExtraBytes = 0L;
  72.         if( mmioRead( hmmioIn, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD) )
  73.             return E_FAIL;
  74.  
  75.         *ppwfxInfo = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ];
  76.         if( NULL == *ppwfxInfo )
  77.             return E_FAIL;
  78.  
  79.         // Copy the bytes from the pcm structure to the waveformatex structure
  80.         memcpy( *ppwfxInfo, &pcmWaveFormat, sizeof(pcmWaveFormat) );
  81.         (*ppwfxInfo)->cbSize = cbExtraBytes;
  82.  
  83.         // Now, read those extra bytes into the structure, if cbExtraAlloc != 0.
  84.         if( mmioRead( hmmioIn, (CHAR*)(((BYTE*)&((*ppwfxInfo)->cbSize))+sizeof(WORD)),
  85.                       cbExtraBytes ) != cbExtraBytes )
  86.         {
  87.             delete *ppwfxInfo;
  88.             *ppwfxInfo = NULL;
  89.             return E_FAIL;
  90.         }
  91.     }
  92.  
  93.     // Ascend the input file out of the 'fmt ' chunk.
  94.     if( 0 != mmioAscend( hmmioIn, &ckIn, 0 ) )
  95.     {
  96.         delete *ppwfxInfo;
  97.         *ppwfxInfo = NULL;
  98.         return E_FAIL;
  99.     }
  100.  
  101.     return S_OK;
  102. }
  103.  
  104.  
  105.  
  106.  
  107. //-----------------------------------------------------------------------------
  108. // Name: WaveOpenFile()
  109. // Desc: This function will open a wave input file and prepare it for reading,
  110. //       so the data can be easily read with WaveReadFile. Returns 0 if
  111. //       successful, the error code if not.
  112. //-----------------------------------------------------------------------------
  113. HRESULT WaveOpenFile( CHAR* strFileName, HMMIO* phmmioIn, WAVEFORMATEX** ppwfxInfo,
  114.                   MMCKINFO* pckInRIFF )
  115. {
  116.     HRESULT hr;
  117.     HMMIO   hmmioIn = NULL;
  118.     
  119.     if( NULL == ( hmmioIn = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF|MMIO_READ ) ) )
  120.         return E_FAIL;
  121.  
  122.     if( FAILED( hr = ReadMMIO( hmmioIn, pckInRIFF, ppwfxInfo ) ) )
  123.     {
  124.         mmioClose( hmmioIn, 0 );
  125.         return hr;
  126.     }
  127.  
  128.     *phmmioIn = hmmioIn;
  129.  
  130.     return S_OK;
  131. }
  132.  
  133.  
  134.  
  135.  
  136. //-----------------------------------------------------------------------------
  137. // Name: WaveStartDataRead()
  138. // Desc: Routine has to be called before WaveReadFile as it searches for the
  139. //       chunk to descend into for reading, that is, the 'data' chunk.  For
  140. //       simplicity, this used to be in the open routine, but was taken out and
  141. //       moved to a separate routine so there was more control on the chunks
  142. //       that are before the data chunk, such as 'fact', etc...
  143. //-----------------------------------------------------------------------------
  144. HRESULT WaveStartDataRead( HMMIO* phmmioIn, MMCKINFO* pckIn,
  145.                            MMCKINFO* pckInRIFF )
  146. {
  147.     // Seek to the data
  148.     if( -1 == mmioSeek( *phmmioIn, pckInRIFF->dwDataOffset + sizeof(FOURCC),
  149.                         SEEK_SET ) )
  150.         return E_FAIL;
  151.  
  152.     // Search the input file for for the 'data' chunk.
  153.     pckIn->ckid = mmioFOURCC('d', 'a', 't', 'a');
  154.     if( 0 != mmioDescend( *phmmioIn, pckIn, pckInRIFF, MMIO_FINDCHUNK ) )
  155.         return E_FAIL;
  156.  
  157.     return S_OK;
  158. }
  159.  
  160.  
  161.  
  162.  
  163. //-----------------------------------------------------------------------------
  164. // Name: WaveReadFile()
  165. // Desc: Reads wave data from the wave file. Make sure we're descended into
  166. //       the data chunk before calling this function.
  167. //          hmmioIn      - Handle to mmio.
  168. //          cbRead       - # of bytes to read.   
  169. //          pbDest       - Destination buffer to put bytes.
  170. //          cbActualRead - # of bytes actually read.
  171. //-----------------------------------------------------------------------------
  172. HRESULT WaveReadFile( HMMIO hmmioIn, UINT cbRead, BYTE* pbDest,
  173.                       MMCKINFO* pckIn, UINT* cbActualRead )
  174. {
  175.     MMIOINFO mmioinfoIn;         // current status of <hmmioIn>
  176.  
  177.     *cbActualRead = 0;
  178.  
  179.     if( 0 != mmioGetInfo( hmmioIn, &mmioinfoIn, 0 ) )
  180.         return E_FAIL;
  181.                 
  182.     UINT cbDataIn = cbRead;
  183.     if( cbDataIn > pckIn->cksize ) 
  184.         cbDataIn = pckIn->cksize;       
  185.  
  186.     pckIn->cksize -= cbDataIn;
  187.     
  188.     for( DWORD cT = 0; cT < cbDataIn; cT++ )
  189.     {
  190.         // Copy the bytes from the io to the buffer.
  191.         if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  192.         {
  193.             if( 0 != mmioAdvance( hmmioIn, &mmioinfoIn, MMIO_READ ) )
  194.                 return E_FAIL;
  195.  
  196.             if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead )
  197.                 return E_FAIL;
  198.         }
  199.  
  200.         // Actual copy.
  201.         *((BYTE*)pbDest+cT) = *((BYTE*)mmioinfoIn.pchNext);
  202.         mmioinfoIn.pchNext++;
  203.     }
  204.  
  205.     if( 0 != mmioSetInfo( hmmioIn, &mmioinfoIn, 0 ) )
  206.         return E_FAIL;
  207.  
  208.     *cbActualRead = cbDataIn;
  209.     return S_OK;
  210. }
  211.  
  212.  
  213.  
  214.   
  215. //-----------------------------------------------------------------------------
  216. // Name: CWaveSoundRead()
  217. // Desc: Constructs the class
  218. //-----------------------------------------------------------------------------
  219. CWaveSoundRead::CWaveSoundRead()
  220. {
  221.     m_pwfx   = NULL;
  222. }
  223.  
  224.  
  225.  
  226.  
  227. //-----------------------------------------------------------------------------
  228. // Name: ~CWaveSoundRead()
  229. // Desc: Destructs the class
  230. //-----------------------------------------------------------------------------
  231. CWaveSoundRead::~CWaveSoundRead()
  232. {
  233.     Close();
  234.     SAFE_DELETE( m_pwfx );
  235. }
  236.  
  237.  
  238.  
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Name: Open()
  242. // Desc: Opens a wave file for reading
  243. //-----------------------------------------------------------------------------
  244. HRESULT CWaveSoundRead::Open( CHAR* strFilename )
  245. {
  246.     SAFE_DELETE( m_pwfx );
  247.  
  248.     HRESULT  hr;
  249.     
  250.     if( FAILED( hr = WaveOpenFile( strFilename, &m_hmmioIn, &m_pwfx, &m_ckInRiff ) ) )
  251.         return hr;
  252.  
  253.     if( FAILED( hr = Reset() ) )
  254.         return hr;
  255.  
  256.     return hr;
  257. }
  258.  
  259.  
  260.  
  261.  
  262. //-----------------------------------------------------------------------------
  263. // Name: Reset()
  264. // Desc: Resets the internal m_ckIn pointer so reading starts from the 
  265. //       beginning of the file again 
  266. //-----------------------------------------------------------------------------
  267. HRESULT CWaveSoundRead::Reset()
  268. {
  269.     return WaveStartDataRead( &m_hmmioIn, &m_ckIn, &m_ckInRiff );
  270. }
  271.  
  272.  
  273.  
  274.  
  275. //-----------------------------------------------------------------------------
  276. // Name: Read()
  277. // Desc: Reads a wave file into a pointer and returns how much read
  278. //       using m_ckIn to determine where to start reading from
  279. //-----------------------------------------------------------------------------
  280. HRESULT CWaveSoundRead::Read( UINT nSizeToRead, BYTE* pbData, UINT* pnSizeRead )
  281. {
  282.     return WaveReadFile( m_hmmioIn, nSizeToRead, pbData, &m_ckIn, pnSizeRead );
  283. }
  284.  
  285.  
  286.  
  287.  
  288. //-----------------------------------------------------------------------------
  289. // Name: Close()
  290. // Desc: Closes an open wave file 
  291. //-----------------------------------------------------------------------------
  292. HRESULT CWaveSoundRead::Close()
  293. {
  294.     mmioClose( m_hmmioIn, 0 );
  295.     return S_OK;
  296. }
  297.  
  298.  
  299.  
  300.